package edu.poly.game.battleship.impl;

import edu.poly.game.battleship.BattleShip;
import edu.poly.game.battleship.BattleShipType;
import edu.poly.game.battleship.Orientation;
import edu.poly.game.player.MissileFireResultType;
import edu.poly.game.util.BoundaryValidationUtil;
import edu.poly.game.util.Coordinate;
import edu.poly.game.util.Dimension;

/**
 * immutable class, for logic safety, once constructed, only implementor should know
 * how to operate this object
 * @author kevint
 *
 */
public class BattleShipImpl implements BattleShip {

	private String name;
	private Coordinate fromCoordinate;
	private Coordinate toCoordinate;
	private BattleShipType battleShipType;
	private boolean destroyed;
	private Orientation orientation;
	private Dimension dimension;
	
	/**
	 * constructor, immutable
	 * @param name ship name
	 * @param fromCoordinate ship starting coordinate
	 * @param battleShipType ship type
	 * @param orientation ship orientation
	 * @param width ship width
	 * @param height ship height
	 */
	public BattleShipImpl(final Coordinate fromCoordinate,
			final BattleShipType battleShipType, final Orientation orientation,
			final Dimension dimension) {
		//by default, upon construction, this ship is not destroyed
		this.destroyed = false;
		this.name = battleShipType.getName();
		this.fromCoordinate = fromCoordinate;
		this.battleShipType = battleShipType;
		this.orientation = orientation;
		this.dimension = dimension;
		//calculate toCoordinate based on orientation here, should not be set by user
		this.toCoordinate = calculateToCoordinate();
	}
	
	private Coordinate calculateToCoordinate() {
		if(this.orientation.equals(Orientation.VERTICLE)) {
			return new Coordinate(this.fromCoordinate.getXCoordinate() + this.dimension.getHeight() - 1,
					this.fromCoordinate.getYCoordinate() + this.dimension.getWidth() - 1);
		} else {
			return new Coordinate(this.fromCoordinate.getXCoordinate() + this.dimension.getWidth() - 1,
					this.fromCoordinate.getYCoordinate() + this.dimension.getHeight() - 1);
		}
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getName() {
		return this.name;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Coordinate getFromCoordinate() {
		return this.fromCoordinate;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Coordinate getToCoordinate() {
		return this.toCoordinate;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public BattleShipType getBattleShipType() {
		return this.battleShipType;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public boolean isDestroyed() {
		return this.destroyed;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Orientation getOrientation() {
		return this.orientation;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public Dimension getShipDimension() {
		return this.dimension;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * Note: 
	 * 	1. if this ship already destroyed, do nothing
	 *  2. else if hit success, set this ship to destroyed
	 *  3. else did not hit, return false
	 */
	@Override
	public MissileFireResultType takeMissileHit(final Coordinate missileCoordinate) {
		boolean isSuccessHit = BoundaryValidationUtil.isWithinBoundary(fromCoordinate, toCoordinate, missileCoordinate);
		if(isSuccessHit == false) {
			return null;
		}
		if(this.isDestroyed()) {
			//since this ship already destroyed, return false, nothing happened
			return MissileFireResultType.HITDESTROYEDSHIP;
		}
		
		if(isSuccessHit) {
			this.destroyed = true;
			return MissileFireResultType.HIT;
		}
		return MissileFireResultType.MISSED;
	}

//	@Override
//	public boolean isWithinRange(final Coordinate coordinate) {
//		return BoundaryValidationUtil.isWithinBoundary(fromCoordinate, toCoordinate, coordinate);
//	}

}
